//
//  Tips.h
//  <19.0>粘贴板和Nil-Targeted Actions
//



### 粘贴板 


粘贴板进程是Mac系统运行的一个进程。应用程序使用'NSPasteboard'类将数据向粘贴板进程中写入和读取。
粘贴板进行程序间的复制粘贴和剪切。

程序可以"将同样的数据以不同的形式复制到粘贴板上"。例如，图片可以进行pdf文档格式或者png格式复制到粘贴板上。"读取时，按照需要的格式读取"，例如使用UTI来标识剪贴板上不同格式类型。

在Mac OS X 10.6之前， 剪贴板API任何时候只能操作一个条目的内容（即使这个条目有多种类型或者表达方式）。10.6之后， Apple升级了粘贴板API，支持操作多个条目。

> 在粘贴板上放数据时,程序一般先回清除粘贴板，然后在往粘贴板上放一个或者多个数据对象。 每一个条目都是粘贴板上一个独立的条目，并且遵循协议'pasteboard-writing'.

> 粘贴板为响应程序的请求，创建了一个对象队列，为粘贴板的每一个条目创建了丰富的表示信息，这也要求对象队列的每个类都遵循协议'pasteboard-writing'.

数据也可以通过粘贴板采用'延迟复制'的技术传递。首先对象要声明所有放到粘贴板的数据的类型，并在需要的时候用delegate方法提供数据。

> Apple也提供了一些支持每种类型的数据粘贴板API,这对应用程序准确控制粘贴板非常有用。
> 也可以有多个粘贴板：一个叫通用粘贴板，用于复制粘贴操作；一个粘贴板主要用于拖拽放置任务；等等。


### NSPasteboard 

//返回NSPasteboard对象，可以实现复制粘贴
NSPasteboard *pBoard = [NSPasteboard generalPasteboard];


//返回指定名称的粘贴板
//APPKIT_EXTERN NSString *NSGeneralPboard;
//APPKIT_EXTERN NSString *NSFontPboard;
//APPKIT_EXTERN NSString *NSRulerPboard;
//APPKIT_EXTERN NSString *NSFindPboard;
//APPKIT_EXTERN NSString *NSDragPboard;
NSPasteboard *pBoardWithName = [NSPasteboard pasteboardWithName:NSGeneralPboard];


//清除粘贴板上的内容 ,返回清除的个数
NSInteger count = [pBoard clearContents];


//>往粘贴板上写对象。包括 NSString /NSAttributeString  /NSURL /NSImage
//>假如复制多个类型的条目，需要通过'pasteboard-writing'协议将类型写到粘贴板上。
- (BOOL)writeObjects:(NSArray<id<NSPasteboardWriting>> *)objects;


//从粘贴板上读对象。 每个粘贴板条目都将返回一个对象。说明对象类型排列顺序的对象队列也必须被传递。并包含这个类充分的描述信息。这个类必须遵循 'NSPasteboardReading协议'
- (nullable NSArray *)readObjectsForClasses:(NSArray<Class> *)classArray options:(nullable NSDictionary<NSString *, id> *)options NS_AVAILABLE_MAC(10_6);





### Nil-Targeted Actions 

众多视图中，究竟如何才能正确发送cut copy paste消息呢？如果选中一个文本框它应该发送消息，选中另一个的时候，消息应该发送给另一个。

为了解决这个问题 ，引入了 Nil-Targeted Actions ：如果target为nil,那么程序会试着发送action消息给多个对象，直到对象有回应。程序也会试着发送消息给keyWindow的first responder，这就是cut、 paste操作。

不仅如此，继承自'NSResponder'的'NSView'、'NSWindow'都有一个叫nextResponder的成员变量。视图的'nextResponder'通常就是它的父视图。 （具体查看"事件响应链"）

> 举例： 一个关闭窗口的菜单项，它有一个 Nil-Target,它的action是 "performClose:"，程序中只有NSWindow才响应。其他都拒绝响应。最终窗口才接受"performClose:"，这样就完成了窗口的关闭。





### 响应链 

在Nil-Targeted Action抛弃之前，视图是怎样响应的呢？


1. keyWindow的fristResponder及responder chain

2. keyWindow的delegate

3. 假如是基于文档的引用程序。还包括NSWindowController以及关键窗口的NSDocument对象。

4. 如果主窗口和关键窗口不同，还会对主窗口进行例行检查:fristResponder、responder chain、delegate、NSWindowController、窗口的NSDocument对象。

5. NSApplication的实例。

6. NSApplication的delegate.

7. NSDocumenttController .





### 哪个对象发送了action消息 


cut/copy/paste的target都是nil , 前面已经知道将消息发送给nil不会产生动作。 所有的target-action消息都是由NSApplication处理。

'NSApplication':
- (BOOL)sendAction:(SEL)action to:(nullable id)target from:(nullable id)sender;

























